<html xmlns="http://www.w3.org/1999/xhtml" id="layout-and-design">
<head>
    <title>Layout and Design</title>
</head>

<body>
 
<h1>Layout and Design</h1>
<p>
LZX enables the creation of applications that have high design values and fluid, graceful interaction.  In this chapter we discuss some basic tools for layout and design.  For more advanced topics and exploration of the aesthetics of OpenLaszlo application design, see the <a href="${design}">Designer's Guide</a>.
</p>
<h2>Declarative positioning of views using layouts</h2>
<p>
By default, all views will position themselves at x="0" y="0" in their coordinate space. That means 
that two sibling views will sit on top of each other. Aside from explicitly positioning the views so they don't overlap, 
the easiest way to separate the siblings is to use a <classname>simplelayout</classname>:</p>


<p>
Instead of specifying each view's coordinates (either through a
constraint or absolutely), you can declare a layout that decides how
sibling views position themselves relative to one another. The
simplest layout is <classname>simplelayout</classname>, which
positions sibling elements one beneath (or to the right of) the other:
</p>

<example title="simple layout">
&lt;canvas height="80"&gt;
  &lt;view bgcolor="yellow" width="100" height="100"&gt;
    <em>&lt;simplelayout axis="y" spacing="5"/&gt;</em>
    &lt;view bgcolor="red" width="20" height="20"/&gt;
    &lt;view bgcolor="blue" width="20" height="20"/&gt;
    &lt;view bgcolor="green" width="20" height="20"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>
Here's an example that shows how to use layouts to resize views in response to user actions:
</p>

<example title="Simple Layout">
&lt;canvas height="140"&gt;
  &lt;class name="coloredRect" width="20" height="80"
         onclick="this.setWidth(this.width+2)"/&gt;
    &lt;view x="10" y="10" name="container"&gt;
      &lt;simplelayout axis="x" spacing="10"/&gt;
      &lt;coloredRect bgcolor="red"/&gt;
      &lt;coloredRect bgcolor="aqua"/&gt;
      &lt;coloredRect bgcolor="yellow"/&gt;
      &lt;coloredRect bgcolor="green"/&gt;
      &lt;coloredRect bgcolor="blue"/&gt;
  &lt;/view&gt;
  
  &lt;button x="10" y="110"&gt;Create A New View
    &lt;method event="onclick"&gt;
      var newView = new coloredRect(container, { bgcolor : 0x000000 });
    &lt;/method&gt;
  &lt;/button&gt;
&lt;/canvas&gt;
</example>

<p>Like all layouts, <classname>simpleLayout</classname> affects how <glossterm>sibling</glossterm> views relate to one another. This remains true even if views are dynamically instantiated. You can set both the axis of a simplelayout as well as the distance between the elements. Also note layouts update as the dimensions of the affected views change.</p>

<p>If you need a specific group of views to be affected by a
simplelayout, but want them to be isolated from the rest of the
application, encase them in a <glossterm>parent view</glossterm>. You
can then specify coordinates on the parent view:</p>

<example title="isolating views">
&lt;canvas height="120"&gt;
  &lt;class name="coloredRect" width="20" height="80"/&gt;
  &lt;view width="50" height="50" bgcolor="yellow"/&gt;
  &lt;!-- Group of horizontally stacked views, isolated from app --&gt;
  &lt;view name="container" x="175" y="20"&gt;
    &lt;simplelayout axis="x" spacing="10"/&gt;
    &lt;coloredRect bgcolor="red"/&gt; 
    &lt;coloredRect bgcolor="blue"/&gt; 
    &lt;coloredRect bgcolor="teal"/&gt; 
    &lt;coloredRect bgcolor="black"/&gt; 
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<h2>Horizontal and Vertical Boxes</h2>
<p>
In addition to layouts, LZX includes the <tagname link="true">hbox</tagname> and <tagname link="true">vbox</tagname> tags that allow you to group views horizontally and vertically. Unlike layouts, which are objects that affect the behavior of their siblings, <tagname>hbox</tagname> and <tagname>vbox</tagname> are themselves views that constrain the layout of their children. Each <tagname>hbox</tagname> or <tagname>vbox</tagname> contains a layout, and the tag syntax allows you to set the layout attributes directly on the hbox or vbox.
</p>
<p>You can also combine <tagname>hbox</tagname> and <tagname>vbox</tagname> elements to form tables. The following example illustrates this. (There are more elegant ways to achieve this effect; we include it here to illustrate the principles.)</p>
<example title="hbox and vbox">
&lt;canvas height="50"&gt;
    &lt;hbox spacing="10"&gt;
    &lt;vbox spacing="10" name="column1" bgcolor="red"&gt;
        &lt;method event="onclick"&gt;
            this.animate('spacing', this.spacing == 10 ? 0 : 10, 1000);
        &lt;/method&gt;
        &lt;text&gt;click&lt;/text&gt;
        &lt;text&gt;to&lt;/text&gt;
        &lt;text&gt;animate&lt;/text&gt;
        &lt;text&gt;spacing&lt;/text&gt;
    &lt;/vbox&gt;
    &lt;vbox spacing="10" name="column2" bgcolor="blue"&gt;
        &lt;method event="onclick"&gt;
            this.animate('spacing', this.spacing == 10 ? 0 : 10, 1000);
        &lt;/method&gt;
        &lt;text&gt;click&lt;/text&gt;
        &lt;text&gt;to&lt;/text&gt;
        &lt;text&gt;animate&lt;/text&gt;
        &lt;text&gt;spacing&lt;/text&gt;
    &lt;/vbox&gt;
    &lt;vbox spacing="10" name="column3" bgcolor="yellow"&gt;
        &lt;method event="onclick"&gt;
            this.animate('spacing', this.spacing == 10 ? 0 : 10, 1000);
        &lt;/method&gt;
        &lt;text&gt;click&lt;/text&gt;
        &lt;text&gt;to&lt;/text&gt;
        &lt;text&gt;animate&lt;/text&gt;
        &lt;text&gt;spacing&lt;/text&gt;
    &lt;/vbox&gt;
    &lt;/hbox&gt;
&lt;/canvas&gt;

</example>

<h2><a name="variations"></a>Variations on Layout</h2>
<p>
As mentioned previously, layouts act upon sibling elements, but they can control more than just spacing. For example, they can
be used to cause views to grow and shrink, as shown below.
</p>


<h3><a name="stableborderlayout"></a>StableBorderLayout</h3>
<p>
A frequent layout problem when designing GUIs is to have an element stretch while its two surrounding siblings maintain a constant size across the stretch axis. LZX solves this problem with the <classname>stableborderlayout</classname>:</p>

<example title="stableborderlayout">
&lt;canvas height="140"&gt;
  &lt;class name="coloredRect" height="80"/&gt;
  
  &lt;view x="10" y="10" name="container" width="200"&gt;
    &lt;stableborderlayout axis="x"/&gt;
    &lt;coloredRect bgcolor="navy" width="20"/&gt;
    &lt;coloredRect bgcolor="yellow"/&gt;
    &lt;coloredRect bgcolor="navy" width="20"/&gt;
  &lt;/view&gt;
  
  &lt;button x="205" y="110"&gt;Increase width of container
    &lt;method event="onclick"&gt;
      container.setWidth(container.width + 10);
    &lt;/method&gt;
  &lt;/button&gt;
  
  &lt;button x="10" y="110"&gt;Decrease width of container
    &lt;method event="onclick"&gt;
      container.setWidth(container.width - 10);
    &lt;/method&gt;
  &lt;/button&gt;
&lt;/canvas&gt;
</example>

<p>
As the name suggests, this layout can be used to create a border with
a stable dimension (width or
height). <classname>stableborderlayout</classname> is very useful for
creating borders, frames and windows. In this example,
<classname>stableborderlayout</classname> is combined with some
constraints to create a 5 pixel blue border:</p>

<example title="creating a border">
&lt;canvas height="200"&gt;
  &lt;!-- Sliders to control width and height --&gt;
  &lt;text x="200" y="22"&gt;Set the width:&lt;/text&gt;
  &lt;slider id="widthSlider" x="200" y="50" width="100" value="50"
          minvalue="20" maxvalue="100"/&gt;
  
  &lt;text x="200" y="92"&gt;Set the height:&lt;/text&gt;
  &lt;slider id="heightSlider" x="200" y="120" width="100" value="50"
          minvalue="20" maxvalue="100"/&gt;
  
  &lt;!-- Blue border --&gt;
  &lt;view width="${widthSlider.value}" height="${heightSlider.value}" 
         x="20" y="20"&gt;
    &lt;stableborderlayout axis="y"/&gt;
    &lt;view bgcolor="blue" height="5" width="${parent.width}"/&gt;
    &lt;view width="${parent.width}"&gt;
      &lt;stableborderlayout axis="x"/&gt;
      &lt;view bgcolor="blue" width="5" height="${parent.height}"/&gt;
      &lt;view height="${parent.height}"/&gt;
      &lt;view bgcolor="blue" width="5" height="${parent.height}"/&gt;
    &lt;/view&gt;
    &lt;view bgcolor="blue" height="5" width="${parent.width}"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>
If you wanted to use the above code frame a particular view irrespective of where it was in the view hierarchy, a good 
way would be to use a <a href="#floatingviews">floating view</a>:
</p>
<example title="using a floating view">
&lt;canvas&gt;
  &lt;!-- A single colored box --&gt;
  &lt;class name="coloredBox" width="50" height="50" bgcolor="0xff0000"/&gt;
  &lt;!-- Blue border; invisible at start --&gt;
  &lt;view id="floater" width="50" height="50" visible="false"&gt;
    &lt;!-- Animate to the coordinates of a given view --&gt;
    &lt;method name="goTo" args="whichBox"&gt;
      this.setVisible(true);
      this.bringToFront();
      var destX = whichBox.getAttributeRelative("x", canvas);
      var destY = whichBox.getAttributeRelative("y", canvas);
      this.animate("x", destX, 1000, false);
      this.animate("y", destY, 1000, false);
    &lt;/method&gt;
    &lt;stableborderlayout axis="y"/&gt;
    &lt;view bgcolor="0xFFFF00" height="5" width="${parent.width}"/&gt;
    &lt;view width="${parent.width}"&gt;
      &lt;stableborderlayout axis="x"/&gt;
      &lt;view bgcolor="0xFFFF00" width="5" height="${parent.height}"/&gt;
      &lt;view height="${parent.height}"/&gt;
      &lt;view bgcolor="0xFFFF00" width="5" height="${parent.height}"/&gt;
    &lt;/view&gt;
    &lt;view bgcolor="0xFFFF00" height="5" width="${parent.width}"/&gt;
  &lt;/view&gt;
  &lt;!-- Controls --&gt;
  &lt;view bgcolor="yellow"&gt;
    &lt;simplelayout axis="y" spacing="10"/&gt;
    &lt;button onclick="floater.goTo(blueBox)"&gt;Go to Blue Box&lt;/button&gt;
    &lt;button onclick="floater.goTo(redBox)"&gt;Go to Red Box&lt;/button&gt;
    &lt;button onclick="floater.goTo(greenBox)"&gt;Go to Green Box&lt;/button&gt;
  &lt;/view&gt;
  &lt;!-- View hierarchy --&gt;
  &lt;view x="20" y="15"&gt;
    &lt;coloredBox id="blueBox" bgcolor="0x0000ff" x="200"/&gt;
    &lt;view x="5" y="40"&gt;
      &lt;coloredBox id="greenBox" bgcolor="0x00ff00" y="150" x="13"/&gt;
      &lt;view x="1" y="90"&gt;
        &lt;coloredBox id="redBox" bgcolor="0xff0000" y="150"/&gt;
      &lt;/view&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>






<h3><a name="constantlayout"></a>Constant Layout</h3>
<p>
The <tagname link="true">constantlayout</tagname> tag is a way of defining a margin. For example, if all of the children of a container needed to be
 indented 10 px from the left hand edge of the container:
</p>

<example title="ConstantLayout">
&lt;canvas height="140"&gt;
  &lt;class name="coloredRect" width="60" height="15"/&gt;

  &lt;view x="10" y="10" name="container" bgcolor="silver" width="80" 
        height="120"&gt;
    &lt;constantlayout axis="x" value="10"/&gt;
    &lt;simplelayout axis="y" spacing="10"/&gt;
    &lt;coloredRect bgcolor="red" width="40"/&gt;
    &lt;coloredRect bgcolor="aqua" width="50"/&gt;
    &lt;coloredRect bgcolor="yellow"/&gt;
    &lt;coloredRect bgcolor="green" width="20"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>Here <tagname>constantlayout</tagname> and
<tagname>simplelayout</tagname> are combined so that the
<tagname>constantlayout</tagname> controls the left, whereas
the<tagname>simplelayout</tagname> dictates the spacing between the
siblings.
</p>


<h2><a name="designconsiderations"></a>Design considerations in LZX programs</h2>
<p>
This chapter 
discusses <code>layouts</code>, which are constructs that allow you to focus on larger design issues by freeing you from the 
tedium of positioning views. Layouts are implemented with <code>constraints</code>, which are described in 
<xref linkend="constraints"/>.
For more on designing the "look and feel" of OpenLaszlo applications, please see
<xref linkend="designers"/>.
</p>


<h3>The view hierarchy</h3>
<p>
Views can be nested inside one another, and they can reference other parts of the view hierarchy using 
dot syntax and/or ids. 
The view hierarchy helps you define how the various elements of your application relate to one another. 
It is helpful to break your application into various elements. Consider a photo-viewing application that has a list of images in 
a right-hand column, and a main stage area for displaying the images to the left. There is also a trash area that we'll cover later. 
At a very high level, you might break your application up as follows:
</p>

<example title="outline of photo application">
&lt;canvas width="800"&gt;
  &lt;view name="stage" width="400" height="300" x="20" bgcolor="0xeaeaea"&gt;
    &lt;!-- Area for viewing images --&gt;
    &lt;text&gt;Stage&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
  
  &lt;view name="listOfImages" width="200" height="300" x="500" bgcolor="0xffff00"&gt;
    &lt;!-- Data-replicated list of images --&gt;
    &lt;text&gt;List of images&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
  
  &lt;view name="trash" width="200" height="75" x="500" y="310" bgcolor="0xff0000"&gt;
    &lt;!-- Trash for disposing of images --&gt;
    &lt;text&gt;Trash&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>
You can use views with background colors when mocking up applications as shown above, to make them easier to prototype.</p>

<p>If you approach the application in this manner, you've effectively broken it up into manageable pieces already. <varname>listOfImages</varname>, <varname>stage</varname> and <varname>trash</varname> could all be developed independently of one another. <varname>listOfImages</varname> would contain the text-list of images that are bound to some data with the descriptive text showing. When the user clicks one of the images, it would call a <method>showImage</method> method on <varname>stage</varname> with the URL of the image to show as an argument.</p>

<p>The replicated views inside of <varname>listOfImages</varname>
would probably be positioned using a layout, and the fact that the
view hierarchy would help here because it would isolate them from the
rest of the application.
</p>


<h4><a name="floatingviews"></a>Floating views</h4>
<p>
The view hierarchy could also be a constraint. Imagine that in the above example, you wanted to be able to drag an item from the list of image names from <varname>listOfImages</varname> to <varname>trash</varname>. 
Frequently in drag-and-drop environments, the original item that was dragged is left in place (although some indication may be given that it is in a transient state, such as being faded out), while a copy of it is dragged. If each of the image titles was draggable, then not only might a dragged item disrupt the arrangement of its siblings, but you wouldn't be able to leave the original intact, in order to obtain the behavior described above. 
</p>

<p>
To get around this problem, you could use a floating view to be the draggable view. A floating view is one that floats on top of the rest of your application, and only appears when dragging:
</p>
<ol>
    <li>User clicks and holds on a view.</li>
    <li>Floating view made visible, and located over clicked view.</li>
    <li>Any visual changes applied to clicked view (e.g. color/alpha transform).</li>
    <li>As mouse moves around, the floating view follows the mouse.</li>
    <li>Onmouseup the floating view disappears, any actions performed, original clicked view restored.</li>
</ol>
<p>
To position the floating view over the clicked view, you can use the <method>getAttributeRelative</method> method of view to obtain the x and y coordinates of the view relative to a view other than its parent. For example, consider the case below:</p>

<example>
&lt;canvas width="800" &gt;
  &lt;!-- An item that will get clicked and dragged --&gt;
  &lt;class name="imageRow" bgcolor="0x93A5FF" width="$once{parent.width}" height="20"&gt;
    &lt;attribute name="text" type="text"/&gt;
    &lt;text name="txt" text="${parent.text}" resize="true"/&gt;
    &lt;method event="onmousedown"&gt;
      this.f = new LzView(canvas, {width: this.width,
                                   height: this.height,
                                   bgcolor: this.bgcolor,
                                   x: this.getAttributeRelative("x", canvas),
                                   y: this.getAttributeRelative("y", canvas),
                                   clickable: true
                                   });
      // Make view follow mouse around
      this.x_offset = this.getMouse("x");
      this.y_offset = this.getMouse("y");
      this.startDraggingFloater();
    &lt;/method&gt;
    
    &lt;method name="startDraggingFloater"&gt;
      this.d = new LzDelegate(this, "adjustFloaterPosition", LzIdle, "onidle");
      this.gm = new LzDelegate(this, "cancelFloater", LzGlobalMouse, "onmouseup");
    &lt;/method&gt;
    
    &lt;method name="adjustFloaterPosition"&gt;
      this.f.setX(canvas.getMouse("x")-this.x_offset);
      this.f.setY(canvas.getMouse("y")-this.y_offset);
    &lt;/method&gt;
    
    &lt;method name="cancelFloater"&gt;
      this.gm.unregisterAll();
      this.d.unregisterAll();
      this.f.destroy();
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;view name="stage" width="400" height="300" x="20" bgcolor="0xeaeaea"&gt;
    &lt;!-- Area for viewing images --&gt;
    &lt;text&gt;Stage&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
  
  &lt;view name="listOfImages" width="200" height="300" x="500" bgcolor="0xffff00"&gt;
    &lt;!-- Data-replicated list of images --&gt;
    &lt;simplelayout axis="y" spacing="2"/&gt;
    
    &lt;imageRow&gt;One&lt;/imageRow&gt;
    &lt;imageRow&gt;Two&lt;/imageRow&gt;
    &lt;imageRow&gt;Three&lt;/imageRow&gt;
  &lt;/view&gt;
  
  &lt;view name="trash" width="200" height="75" x="500" y="310" bgcolor="0xff0000"&gt;
    &lt;!-- Trash for disposing of images --&gt;
    &lt;text&gt;Trash&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>


<p>To achieve this, you could create a view from script when the mouse goes down over one of the views you want to drag:
</p>

<p>
This code is not easy to read, although conceptually it's fairly simple &#x2014; 
"create a new view when the mouse button is depressed, and drag it until the mouse button is released". 
Note also that you have to listen out for the global <event>onmouseup</event> event instead of the <event>onmouseup</event> on the dynamically created view. Because it was positioned under the cursor after the mouse was down, the event system does not get notified when the mouse goes up over it.</p>
<p>
This approach is fairly laborious &#x2014; you have to copy all of the attributes of the original view to the new one. If you wanted to have the text field appear in the dragged view, you would have to create a new text field to match it at run-time. As the dragged view becomes more complex, it will take longer to instantiate when the user depresses the mouse button, since view instantiation is fairly processor-expensive.</p>
<p>

A better approach would be to have the floating view ready in advance:
</p>

<example title="building a &quot;floating view&quot;">
&lt;canvas width="800" &gt;
  &lt;!-- A draggable floating view --&gt;
  &lt;class name="floater" height="20" bgcolor="0x93A5FF" visible="false"&gt;
    &lt;dragstate name="dragger"/&gt;
    &lt;text name="txt" width="100"/&gt;
    &lt;method name="showFloater" args="xpos, ypos, itemwidth, itemlabel"&gt;
      myfloater.bringToFront();
      this.setX(xpos);
      this.setY(ypos);
      this.setWidth(itemwidth);
      this.txt.setText(itemlabel);
      this.setVisible(true)
      this.gm = new LzDelegate(this, "cancelFloater", LzGlobalMouse, "onmouseup");
      this.setVisible(true);
      this.dragger.apply();
    &lt;/method&gt;

    &lt;method name="cancelFloater"&gt;
      this.dragger.remove();
      this.setVisible(false);
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;!-- An instance of the floater --&gt;
  &lt;floater id="myfloater"/&gt;
  
  &lt;!-- An item that will get clicked and dragged --&gt;
  &lt;class name="imageRow" bgcolor="0x93A5FF" width="$once{parent.width}" height="20"&gt;
    &lt;attribute name="text" type="text"/&gt;
    &lt;text name="txt" text="${parent.text}" resize="true"/&gt;
    &lt;method event="onmousedown"&gt;
      myfloater.showFloater(this.getAttributeRelative("x", canvas),
                            this.getAttributeRelative("y", canvas),
                            this.width,
                            this.txt.getText());
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;view name="stage" width="400" height="300" x="20" bgcolor="0xeaeaea"&gt;
    &lt;!-- Area for viewing images --&gt;
    &lt;text&gt;Stage&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
  
  &lt;view name="listOfImages" width="200" height="300" x="500" bgcolor="0xffff00"&gt;
    &lt;!-- Data-replicated list of images --&gt;
    &lt;simplelayout axis="y" spacing="2"/&gt;
    &lt;imageRow&gt;One&lt;/imageRow&gt;
    &lt;imageRow&gt;Two&lt;/imageRow&gt;
    &lt;imageRow&gt;Three&lt;/imageRow&gt;
  &lt;/view&gt;
  
  &lt;view name="trash" width="200" height="75" x="500" y="310" bgcolor="0xff0000"&gt;
    &lt;!-- Trash for disposing of images --&gt;
    &lt;text&gt;Trash&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>
This code is much cleaner, and the floater code is now completely independent of the <tt>imagerow</tt> code. Individual properties of the floater can still be set (in this case they're passed as arguments to the showFloater method).
</p>
<p>
Taking this a step further, if our list of images were replicated against a dataset an even more elegant approach would be to pass the data node of the replicated <tt>imageRow</tt> instance to the floater, and have the floater do the right thing with the data.
</p>
<example title="Using a dataset to drive layouts">
&lt;canvas width="800" &gt;
  &lt;!-- The data that provides the images --&gt;
  &lt;dataset name="ds_items"&gt;
    &lt;items&gt;
      &lt;item description="One" src="one.jpg"/&gt;
      &lt;item description="Two" src="two.jpg"/&gt;
      &lt;item description="Three" src="three.jpg"/&gt;
    &lt;/items&gt;
  &lt;/dataset&gt;
  
  &lt;!-- A draggable floating view --&gt;
  &lt;class name="floater" height="20" bgcolor="0x93A5FF" visible="false"
         <em>datapath=""</em>&gt;
    &lt;dragstate name="dragger"/&gt;
    
    &lt;text name="txt" datapath="@description" resize="true"/&gt;
    &lt;text name="imgurl" datapath="@src" resize="true" align="right"/&gt;
    
    &lt;method name="showFloater" args="xpos, ypos, itemwidth, dataNode"&gt;
      myfloater.bringToFront();
      this.setX(xpos);
      this.setY(ypos);
      this.setWidth(itemwidth);
      <em>this.datapath.setPointer(dataNode);</em>
      this.setVisible(true)
      this.gm = new LzDelegate(this, "cancelFloater", LzGlobalMouse, "onmouseup");
      this.setVisible(true);
      this.dragger.apply();
    &lt;/method&gt;
    
    &lt;method name="cancelFloater"&gt;
      this.dragger.remove();
      this.setVisible(false);
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;!-- An instance of the floater --&gt;
  &lt;floater id="myfloater"/&gt;
  
  &lt;!-- An item that will get clicked and dragged --&gt;
  &lt;class name="imageRow" bgcolor="0x93A5FF" 
         width="$once{parent.width}" 
         height="20"&gt;
    &lt;attribute name="text" type="text"/&gt;
    &lt;text name="txt" datapath="@description" resize="true"/&gt;
    &lt;method event="onmousedown"&gt;
      myfloater.showFloater(this.getAttributeRelative("x", canvas),
                            this.getAttributeRelative("y", canvas),
                            this.width,
                            <em>this.datapath.p</em>);
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;view name="stage" width="400" height="300" x="20" bgcolor="0xeaeaea"&gt;
    &lt;!-- Area for viewing images --&gt;
    &lt;text&gt;Stage&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
  
  &lt;view name="listOfImages" width="200" height="300" x="500" 
        bgcolor="0xffff00"
        datapath="ds_items:/items"&gt;
    &lt;!-- Data-replicated list of images --&gt;
    &lt;simplelayout axis="y" spacing="2"/&gt;
    &lt;imageRow datapath="item"/&gt;
  &lt;/view&gt;
  
  &lt;view name="trash" width="200" height="75" x="500" y="310" bgcolor="0xff0000"&gt;
    &lt;!-- Trash for disposing of images --&gt;
    &lt;text&gt;Trash&lt;/text&gt;
    &lt;!-- ... --&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>
See the Reference for an explanation of the <classname link="true">LzNode</classname> call.
</p>

<p>
The floater must have an empty datapath assigned in advance. Notice how since only a pointer to the <classname>LzNode</classname> element is passed to the floating view, the floater can access attributes of the data that were not referenced in the <tt>imageRow</tt> class (for example,the <tt>src</tt> attribute). This can become particularly useful when you want to "drop" the floater somewhere. The drop target may need to access other data properties (or even delete the XML node in the dataset), and passing a pointer to it saves retracing it.</p>
<p>

A floating view is not only for draggable objects. If you wanted to frame a specified view, regardless of where it was in the view hierarchy, you might also find a floating view to be the best option. See the <a href="#stableborderlayout">StableBorderLayout</a> section for more.
</p>

<h4>Resources and ignoring layouts</h4>

<p>
You should avoid placing views inside of views with a
resource. Instead, to have a background image in a container view, have
a view that attaches the resource be a child of the parent view. Use
<code>options="ignorelayout"</code> to prevent the background image
from being affected by any layouts that act upon the children of its
container:
</p>

<example extract="false" title="ignorelayout">
&lt;view name="container"&gt;
  &lt;view resource="someimg.jpg" options="ignorelayout"/&gt;
  &lt;view name="childView"/&gt;
&lt;/view&gt;
</example>






<h2>Scripting and Layouts</h2>

<h3><a name="addressing"></a>Addressing Layouts</h3>

<p>Since a layout extends Node, it can be addressed using dot syntax:</p>

<example extract="false">
&lt;canvas height="140"&gt;
  &lt;class name="coloredRect" width="20" height="80"/&gt;

  &lt;view name="container"&gt;
    &lt;simplelayout name="slayout" axis="x" spacing="10"/&gt;
    &lt;coloredRect bgcolor="red"/&gt;
    &lt;coloredRect bgcolor="aqua"/&gt;
    &lt;coloredRect bgcolor="yellow"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>In the above example, the layout could be accessed by:
<code>container.slayout</code>.</p>

<p>You might need to address a layout in script, in order to change
one of its attributes at run-time, to call the layout's
<method>update</method> method, or to lock it. A layout can also have
an id, so that it can be accessed globally.</p>
<h3>Layouts Array</h3>
<p>
All nodes
have a layouts array, which contains pointers to all of the layouts
that act upon its children:</p>

<example title="Addressing Layouts">
&lt;canvas height="180"&gt;
  &lt;class name="coloredSquare" width="20" height="20"/&gt;

  &lt;view name="container" bgcolor="silver" x="10" y="10"&gt;
    &lt;simplelayout axis="x" spacing="2"/&gt;
    &lt;simplelayout id="yLayout" axis="y" spacing="2"/&gt;

    &lt;coloredSquare bgcolor="red"/&gt;
    &lt;coloredSquare bgcolor="red"/&gt;
    &lt;coloredSquare bgcolor="red"/&gt;
    &lt;coloredSquare bgcolor="red"/&gt;
    &lt;coloredSquare bgcolor="red"/&gt;
  &lt;/view&gt;

  &lt;button y="150" x="10"&gt;Increase spacing of BOTH x and y layouts
    &lt;method event="onclick"&gt;
      &lt;![CDATA[
      for (var i=0; i&lt;container.layouts.length; i++) {
          var lyt = container.layouts[i];
          lyt.setAttribute('spacing', lyt.spacing + 2);
      }
      ]]&gt;
    &lt;/method&gt;
  &lt;/button&gt;

  &lt;button y="150" x="280"&gt;Increase spacing of y layout ONLY
    &lt;method event="onclick"&gt;
      yLayout.setAttribute('spacing', yLayout.spacing + 2);
    &lt;/method&gt;
  &lt;/button&gt;
&lt;/canvas&gt;
</example>



<h3>Locking and Unlocking Layouts</h3>

<p>Layouts can be locked and unlocked using the <method>lock</method>
and <method>unlock</method> methods respectively (inherited from the
<classname link="true">layout</classname> class).  When you lock a layout, you prevent it from
updating. For example, if you click the colored boxes in the following
example to enlarge them, the simplelayout will automatically update,
and the spacing between the boxes will remain consistent. However, if
you lock the layout, then grow the boxes, the simplelayout will not
update, until the <method>unlock</method> method is called on the
layout:</p>

<example title="Locking and Unlocking Layouts">
&lt;canvas height="140"&gt;
  &lt;class name="coloredRect" width="20" height="80"
         onclick="this.setWidth(this.width+2)"/&gt;

  &lt;view x="10" y="10" name="container"&gt;
    &lt;simplelayout name="slayout" axis="x" spacing="10"/&gt;
    &lt;coloredRect bgcolor="red"/&gt;
    &lt;coloredRect bgcolor="aqua"/&gt;
    &lt;coloredRect bgcolor="yellow"/&gt;
    &lt;coloredRect bgcolor="green"/&gt;
    &lt;coloredRect bgcolor="blue"/&gt;
  &lt;/view&gt;

  &lt;button x="10" y="110"&gt;Lock
    &lt;method event="onclick"&gt;
      container.slayout.lock();
    &lt;/method&gt;
  &lt;/button&gt;

  &lt;button x="70" y="110"&gt;Unlock
    &lt;method event="onclick"&gt;
      container.slayout.unlock();
    &lt;/method&gt;
  &lt;/button&gt;
&lt;/canvas&gt;
</example>

<p>The <method>lock</method> method sets the layout's
<attribute>locked</attribute> attribute to true. The <method>unlock</method> method
calls the layout's <method>update</method> method, then sets the
<attribute>locked</attribute> attribute to <code>false</code>.</p>

<h2>Animating layout</h2>
<p>Layouts can be animated; that is, the properties of the layout can be set to vary over time.
For an example and an explanation of how this is done, see <xref linkend="animation"/></p>

<h2>Writing Custom Layouts</h2>
<p>
When none of the LFC layouts do what you need, you can write a custom layout of your own. This section shows the essential aspects of building one.
</p>


<h3>The <method>update</method> method</h3>

<p>The <method>update</method> method is the most important method in
a layout &#x2014; it controls what the layout does. For example, here
is a very basic custom layout that spaces views 20px apart. This
is similar to the behavior of the<tagname>simplelayout</tagname>, but unlike <tagname>simplelayout</tagname> this one spaces
the left hand edge of the views, rather than distributing them
evenly:</p>

<example title="Updating a layout">
&lt;canvas height="100"&gt;
  &lt;class name="col" clickable="true" bgcolor="blue" width="15" height="80"/&gt;

  &lt;layout&gt;
    &lt;attribute name="spacing" value="25" type="number"/&gt;
    &lt;method name="addSubview" args="s"&gt;
      super.addSubview(s);
      this.update();
    &lt;/method&gt;

    &lt;method name="update"&gt;
      &lt;![CDATA[  
      if (this.locked) return;
      this.locked = true;
      for (var i = 0; i &lt; subviews.length; i++){
          subviews[i].setAttribute('x',  i * this.spacing);
      }
      this.locked= false;
      ]]&gt;
    &lt;/method&gt;
  &lt;/layout&gt;

  &lt;col/&gt;
  &lt;col/&gt;
  &lt;col/&gt;
  &lt;col/&gt;
&lt;/canvas&gt;
</example>

<p>All layouts have a <tt>subviews</tt> array, which allows you to cycle through the sibling views and adjust their properties accordingly. The <method>addSubview</method> method is automatically called whenever a view is added&#8212;at init time, when a view is dynamically generated from script or via data replication. It ensures that the <method>update</method> method gets called so that the layout updates. If the <method>addSubview</method>method were not present, the above example would still look fine when the application first started, but any dynamically created views would appear out of the layout.</p>

<p>Notice both:</p>

<ol>
    <li>The test for the <attribute>locked</attribute> attribute (<code>if (this.locked) return;</code>) to ensure conformance with normal layout response to the locking and unlocking of layouts.</li>
    <li>The use of the <attribute>locked</attribute> attribute in the <method>update</method> method (<code>this.locked = true;</code> and <code>this.locked = false;</code>) to prevent simultaneous changes to the layout.</li>
</ol>
<p>
Here is a slightly more complicated example. In fact the layout defined below is the same as <code>&lt;simplelayout axis="x" spacing="10"/&gt;</code>.
</p>
<example title="Horizontal Simplelayout">
&lt;canvas height="100"&gt;
  &lt;class name="col" clickable="true" bgcolor="blue" 
         width="20" height="80" onclick="this.setWidth(this.width+2)"/&gt;
  &lt;layout&gt;
    &lt;attribute name="spacing" value="10" type="number"/&gt;
    &lt;method name="addSubview" args="s"&gt;
      <em>this.updateDelegate.register(s, "onwidth");</em>
      super.addSubview(s);
      this.update();
    &lt;/method&gt;
    &lt;method name="update"&gt;
      &lt;![CDATA[  
      if (this.locked) return;
      this.locked = true;
      var indent = 0;
      for (var i = 0; i &lt; subviews.length; i++){
          <em>var s = subviews[i];
          s.setAttribute('x',  indent);
          indent += s.width + this.spacing;</em>
      }
      this.locked = false;
      ]]&gt;
    &lt;/method&gt;
  &lt;/layout&gt;

  &lt;col/&gt;
  &lt;col/&gt;
  &lt;col/&gt;
  &lt;col/&gt;
  &lt;col/&gt;
  &lt;col/&gt;
&lt;/canvas&gt;
</example>

<p>
Notice that the <method>update</method> method is slightly different
now &#x2014; it adds up the total widths of the preceding siblings
(adding the spacing) and sets the x to the total. That is the basic
algorithm for simplelayout. Another very important difference is that
the <method>addSubview</method> method registers the inherited
<method>updateDelegate</method> to listen for changes to that
subview's width. <method>updateDelegate</method> is a delegate that
all subclasses of layout have. It calls that layout's
<method>update</method> method. In this example, the layout needs to
update when the width of any of the sibling views changes, so the call
to register it happens in the <method>addSubview</method> method.
</p>






</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
